<template>
  <div
    class="CardCarouselMultiRowArticles_wrap"
    ref="parent"
    @mouseenter="isHover = true"
    @mouseleave="isHover = false"
  >
    <div
      :style="{
        backgroundColor: modelValue?.bgColor,
        marginTop: '30px',
        marginBottom: '30px',
      }"
      class="CardCarouselMultiRowArticles_container"
      :class="[widthClass]"
    >
      <client-only>
        <Swiper
          ref="swiperRef"
          :modules="modules"
          :centered-slides="false"
          :speed="600"
          :slides-per-view="1"
          :slides-per-group="1"
          :space-between="16"
          :loop="true"
          :breakpoints="swiperBreakpoints"
          :auto-height="true"
          class="swiper card-carousel__swiper"
          @swiper="onSwiperReady"
          @slideChange="onSwiperSlideChange"
        >
          <SwiperSlide
            v-for="(slide, slideIdx) in listChunck"
            class="swiper-slide"
            :key="slideIdx"
          >
            <div
              v-for="rowIdx in computeRowsPerSlide(slide)"
              :key="rowIdx"
              class="row"
              :class="[`row-cols-${columnsPerRow}`]"
              :style="{ '--cc-cols': columnsPerRow }"
            >
              <div
                class="slide-content col"
                v-for="item in getRowItems(slide, rowIdx)"
                :key="item.key || item.slug"
              >
                <CardArticle :componentProps="item" />
              </div>
            </div>
          </SwiperSlide>
        </Swiper>
      </client-only>
      <div class="mt-10 mt-md-12" v-show="showSlidesPagination">
        <SlidesPagination
          :currentIndex="currentIndex"
          @updatePage="updatePage"
          :count="listChunck.length"
          @slidePrev="slidePrev"
          @slideNext="slideNext"
          :isLoop="true"
          dark
        />
      </div>
    </div>

    <Operate
      v-if="!isPreview"
      v-model:show="isHover"
      @handle-edit="showSetting = true"
      @handle-delete="handleDelete"
      @handle-copy="handleCopy"
      @handle-paste="handlePaste"
    ></Operate>
  </div>

  <Setting
    v-if="!isPreview"
    v-model:show="showSetting"
    :data="modelValue"
  ></Setting>
</template>

<script lang="ts" setup>
import {
  nextTick,
  ref,
  computed,
  watch,
  onMounted,
  onBeforeUnmount,
} from "vue";
import { randomString } from "@/utils/common";
import Setting from "./setting.vue";
import Operate from "@/common/Operate/index.vue";
import SlidesPagination from "@/common/SlidesPagination/index.vue";
import CardArticle from "@/common/CardArticle/index.vue";
import { Swiper, SwiperSlide } from "swiper/vue";
import { Navigation, Pagination, Autoplay } from "swiper/modules";
import "swiper/css";
import "swiper/css/navigation";
import "swiper/css/pagination";
// import axios from "axios";

// 定义组件名称
defineOptions({
  name: "CardCarouselMultiRowArticles",
});

const props = defineProps({
  modelValue: {
    type: Object,
    default: () => {},
  },

  // 是否预览
  isPreview: {
    type: Boolean,
    default: true,
  },
});
// console.log("!!!!", props.modelValue);
const emit = defineEmits([
  "update:modelValue",
  "handleDelete",
  "handleCopy",
  "handlePaste",
  "handleClick",
  "showLightboxVideo",
  "showLightBoxImage",
]);

// Swiper 模块
const modules = [Navigation, Pagination, Autoplay];

const isHover = ref<boolean>(false);
const showSetting = ref<boolean>(false);

const handleDelete = () => {
  emit("handleDelete", props.modelValue.id);
};

const handleCopy = () => {
  emit("handleCopy", props.modelValue);
};

const handlePaste = (type: string) => {
  emit("handlePaste", type);
};

const handleInit = () => {
  if (props.modelValue && props.modelValue.data) return; // 有数据不用初始化
  const data = {
    id: props.modelValue?.id || randomString(),
    type: "CardCarouselMultiRowArticles",
    bgColor: "#ffffff",
    // 预设每行 2 行，方便展示多行网格
    width: "default",
    row: 4,
    mobileRow: 2,
    // 模拟文章数据，便于本地开发预览
    list: [
      {
        key: "art-001",
        title: "示例文章八：完整一页 8 条",
        desc: "perChunk=4×row(2)=8，正好一页显示 8 个卡片。",
        date: "2024-03-08",
        category: "news",
        link: "https://example.com/articles/art-008",
        labelName: "NEWS",
        image:
          "https://images.unsplash.com/photo-1677442136019-21780ecad995?w=800&h=600&fit=crop",
        alt: "人工智能概念图",
      },
      {
        key: "art-002",
        title: "示例文章八：完整一页 8 条",
        desc: "perChunk=4×row(2)=8，正好一页显示 8 个卡片。",
        date: "2024-03-08",
        category: "news",
        link: "https://example.com/articles/art-008",
        labelName: "NEWS",
        image:
          "https://images.unsplash.com/photo-1677442136019-21780ecad995?w=800&h=600&fit=crop",
        alt: "人工智能概念图",
      },
      {
        key: "art-003",
        title: "示例文章八：完整一页 8 条",
        desc: "perChunk=4×row(2)=8，正好一页显示 8 个卡片。",
        date: "2024-03-08",
        category: "news",
        link: "https://example.com/articles/art-008",
        labelName: "NEWS",
        image:
          "https://images.unsplash.com/photo-1677442136019-21780ecad995?w=800&h=600&fit=crop",
        alt: "人工智能概念图",
      },
      {
        key: "art-004",
        title: "示例文章八：完整一页 8 条",
        desc: "perChunk=4×row(2)=8，正好一页显示 8 个卡片。",
        date: "2024-03-08",
        category: "news",
        link: "https://example.com/articles/art-008",
        labelName: "NEWS",
        image:
          "https://images.unsplash.com/photo-1677442136019-21780ecad995?w=800&h=600&fit=crop",
        alt: "人工智能概念图",
      },
      {
        key: "art-005",
        title: "示例文章八：完整一页 8 条",
        desc: "perChunk=4×row(2)=8，正好一页显示 8 个卡片。",
        date: "2024-03-08",
        category: "news",
        link: "https://example.com/articles/art-008",
        labelName: "NEWS",
        image:
          "https://images.unsplash.com/photo-1677442136019-21780ecad995?w=800&h=600&fit=crop",
        alt: "人工智能概念图",
      },
    ],
  };
  emit("update:modelValue", data);
};
handleInit();
const isClient = ref(false);
const parent = ref<HTMLElement | null>(null);
const swiperRef = ref<any>(null);
const swiperInstance = ref<any>(null);

const onSwiperReady = (swiper: any) => {
  swiperInstance.value = swiper;
};

const currentIndex = ref(0);
// const slideNum = ref(1); // 未使用，移除
const listChunck = ref<any[][]>([]);
const articleData = ref<{ data: any[]; meta: Record<string, any> }>({
  data: [],
  meta: {},
});
const mediaList = ref<any[]>([]);

const classes = computed(() => props.modelValue?.classes ?? null);
const style = computed(() => props.modelValue?.style ?? null);
const apiType = computed(() => props.modelValue?.type ?? "articles");
const width = computed(() => props.modelValue?.width ?? null);
const row = computed(() => props.modelValue?.row ?? 2);
const mobileRow = computed(() => props.modelValue?.mobileRow ?? 2);
const apiLink = computed(() => props.modelValue?.apiLink ?? null);

// 用于请求头；按新项目情况调整
const website = computed(
  () => props.modelValue?.website ?? import.meta.env.VITE_WEBSITE ?? ""
);
const locale = computed(() => props.modelValue?.locale ?? "en");

const vsWidth = ref(1024);
// columns per row: PC uses row, mobile uses mobileRow
const columnsPerRow = computed(() =>
  vsWidth.value >= 768 ? row.value : mobileRow.value
);
// items per slide: two rows per slide when data allows
const itemsPerSlide = computed(() => columnsPerRow.value * 2);
// helper methods for template row rendering
const computeRowsPerSlide = (slide: any[]) =>
  Math.min(2, Math.ceil(slide.length / columnsPerRow.value));
const getRowItems = (slide: any[], rowIdx: number) => {
  const start = (rowIdx - 1) * columnsPerRow.value;
  const end = start + columnsPerRow.value;
  return slide.slice(start, end);
};
const perChunk = computed(() => row.value);
const perRowChunk = computed(() =>
  vsWidth.value >= 768 ? (vsWidth.value >= 1024 ? 4 : 3) : 2
);

const list = computed(() => {
  if (props.modelValue?.getDataType) return articleData.value.data;
  if (apiLink.value) return mediaList.value;
  return props.modelValue?.list ?? [];
});
const showSlidesPagination = computed(() => listChunck.value.length > 1);

const swiper = computed(() => swiperRef.value?.swiper ?? null);

const swiperBreakpoints = {
  768: {
    slidesPerView: "auto",
    slidesPerGroup: 1,
    spaceBetween: 16,
  },
  1024: {
    slidesPerView: 1,
    slidesPerGroup: 1,
    spaceBetween: 16,
  },
};

watch(currentIndex, () => {
  scrollTo(parent.value);
});

watch([list, itemsPerSlide], () => {
  listChuncked();
});
// 新增：widthClass，模仿 CustomIframe 并使用全局容器类
const widthClass = computed(() => {
  const w = props.modelValue?.width as string | number | undefined;
  if (!w || w === "default") return "container-content";
  if (typeof w === "string") {
    if (w.startsWith("container-content-")) return w;
    const map: Record<string, string> = {
      small: "container-content-small",
      middle: "container-content-middle",
      medium: "container-content-middle",
      max: "container-content-max",
    };
    return map[w] || "container-content";
  }
  if (typeof w === "number") {
    return `container-content-${w}`;
  }
  return "container-content";
});
const listChuncked = () => {
  const src = list.value as any[];
  const result: any[][] = [];
  src.forEach((item, index) => {
    const chunkIndex = Math.floor(index / itemsPerSlide.value);
    if (!result[chunkIndex]) result[chunkIndex] = [];
    result[chunkIndex].push(item);
  });
  listChunck.value = result;
};

const onSwiperSlideChange = (swiper: any) => {
  currentIndex.value =
    swiper?.realIndex ?? swiperInstance.value?.realIndex ?? 0;
  removeAssetsClickHandler();
  addAssetsClickHandler();
};

const updatePage = (idx: number) => {
  swiperInstance.value?.slideToLoop?.(idx, 600);
};

const slidePrev = () => {
  swiperInstance.value?.slidePrev?.(600);
};

const slideNext = () => {
  swiperInstance.value?.slideNext?.(600);
};

const openLightboxVideo = (item: any) => {
  if (item.video_type === "outer") return;
  const modalList = list.value.filter(
    (v: any) => v.video_type !== "outer" && v.type !== "photo"
  );
  const modalIdx = modalList.findIndex((v: any) => v.slug === item.slug);
  emit("showLightboxVideo", {
    idx: modalIdx,
    list: modalList,
  });
};

const openLightboxImage = (item: any) => {
  const modalList = list.value.filter((v: any) => v.type === "photo");
  const modalIdx = modalList.findIndex((v: any) => v.slug === item.slug);
  emit("showLightBoxImage", {
    idx: modalIdx,
    url: item.url,
    text: item.text || item.title,
    list: modalList,
  });
};

const scrollTo = (ele: HTMLElement | null) => {
  if (!ele || !isClient.value) return;
  const fixPx = vsWidth.value >= 1024 ? 170 : 150;
  const rect = ele.getBoundingClientRect();
  const top = rect.top + window.pageYOffset - fixPx;
  window.scroll({
    top,
    left: 0,
    behavior: "smooth",
  });
};

const assetsOnClick = (e: Event) => {
  const target = e.currentTarget as HTMLElement;
  const key = target?.dataset.slug as string;
  const mediaType = target?.dataset.type as string;
  const item = list.value.find((v: any) => v.key == key || v.slug == key);
  if (!item) return;
  mediaType === "photo" ? openLightboxImage(item) : openLightboxVideo(item);
};

const addAssetsClickHandler = () => {
  if (!isClient.value) return;
  Array.from(document.getElementsByClassName("card-asset")).forEach((v) => {
    v.addEventListener("click", assetsOnClick);
  });
  Array.from(document.getElementsByClassName("card-video")).forEach((v) => {
    v.addEventListener("click", assetsOnClick);
  });
};

const removeAssetsClickHandler = () => {
  if (!isClient.value) return;
  Array.from(document.getElementsByClassName("card-asset")).forEach((v) => {
    v.removeEventListener("click", assetsOnClick);
  });
  Array.from(document.getElementsByClassName("card-video")).forEach((v) => {
    v.removeEventListener("click", assetsOnClick);
  });
};

// async function getData() {
//   if (props.modelValue?.getDataType) {
//     const url = `/component/production/${apiType.value}?category=${props.modelValue.getDataType}&per_page=99&page=${currentIndex.value}`;
//     const headers = { website: `${website.value}-${locale.value}` };
//     const res = await axios.get(url, { headers });
//     articleData.value = res.data;
//   }
//   if (apiLink.value) {
//     const url = apiLink.value as string;
//     const headers = { website: `${website.value}-${locale.value}` };
//     const { data } = await axios.get(url, { headers });
//     mediaList.value = data.data;
//   }
//   listChuncked();
// }

onMounted(() => {
  isClient.value = true;
  vsWidth.value = window.innerWidth;
  window.addEventListener("resize", () => {
    vsWidth.value = window.innerWidth;
  });
  // getData();
});

onBeforeUnmount(() => {
  removeAssetsClickHandler();
});
</script>

<style lang="scss" scoped>
.CardCarouselMultiRowArticles_wrap {
  position: relative;
}
.card-carousel-multi-row {
  &__wrapper {
    @media (max-width: 767.98px) {
      padding-left: 0;
      padding-right: 0;
    }
  }
  .row {
    --bs-gutter-x: 16px;
    --bs-gutter-y: 32px;
    @media (max-width: 767.98px) {
      --bs-gutter-x: 8px;
      --bs-gutter-y: 28px;
    }
  }
  &__title {
    color: #0032a0;
    margin-bottom: 24px;
    @media (max-width: 767.98px) {
      margin-bottom: 12px;
    }
  }
}

/* 让 Swiper 高度随活动页内容自适应 */
.card-carousel__swiper {
  width: 100%;
}
:deep(.swiper) {
  height: auto;
}
:deep(.swiper-slide) {
  height: auto;
}

/* 保证每个 .slide-content 按列数计算一致宽度，不会在少数据时占满整页 */
:deep(.card-carousel__swiper .row) {
  align-items: flex-start;
}
:deep(.card-carousel__swiper .row .slide-content) {
  flex: 0 0 calc(100% / var(--cc-cols));
  max-width: calc(100% / var(--cc-cols));
}
</style>
